package com.duobaoyu.dby.supply.biz.service.queue.core;

import com.duobaoyu.dby.supply.core.delay.config.RedissonQueue;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.Environment;

/**
 * Created by shuming on 2023/9/27 16:12
 */
public class DistributionQueueBeanFactoryPostProcessor implements BeanFactoryPostProcessor, EnvironmentAware {

	private final String DISTRIBUTION_QUEUE_PREFIX = "distribution.queue";
	private Environment environment;

	private static void registerRedissonQueue(DistributionQueueProperties jobProperties, DefaultListableBeanFactory defaultListableBeanFactory) {
		if (CollectionUtils.isNotEmpty(jobProperties.getTopics())) {
			jobProperties.getTopics().forEach(e -> {
				BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(RedissonQueue.class);
				beanDefinitionBuilder.addConstructorArgValue(e.getTopicName());
				beanDefinitionBuilder.addConstructorArgValue(e.getDelay());
				defaultListableBeanFactory.registerBeanDefinition(e.getTopicName(), beanDefinitionBuilder.getRawBeanDefinition());
			});
		}
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

		DefaultListableBeanFactory defaultListableBeanFactory
				= (DefaultListableBeanFactory) beanFactory;
		DistributionQueueProperties distributionQueueProperties = getDistributionQueueProperties();
		registerRedissonQueue(distributionQueueProperties, defaultListableBeanFactory);
	}

	private DistributionQueueProperties getDistributionQueueProperties() {
		DistributionQueueProperties jobProperties = new DistributionQueueProperties();
		Binder binder = Binder.get(environment);
		ResolvableType type = ResolvableType.forClass(DistributionQueueProperties.class);
		Bindable<?> target = Bindable.of(type).withExistingValue(jobProperties);
		binder.bind(DISTRIBUTION_QUEUE_PREFIX, target);
		return jobProperties;
	}


	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}
}
